//! \file Main.c
//! \brief TODO: Document
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------

//#include "DataTypes.h"
//#include <stdlib.h>
//#include <SDL/SDL.h>    // TODO: temporary once all the SDL testing is done.
//#include "Dice.h"       // TODO: temporary for testing, remove once complete.
//#include "DdRules.h"    // TODO: temporary for testing, remove once complete.
//#include "XmlManager.h" // TODO: temporary for testing.
//#include "UI.h"         // TODO: temporary for testing.
//#include "DataBase.h"   // TODO: temporary for testing.
#include "Core.h"
#include "Db.h"
#include "Gui.h"
//#include "Ui.h"
#include <unistd.h>

//using namespace Core;
using namespace std;



// =====[ Local Definitions ]===================================================

// =====[ Local DataTypes ]=====================================================

// =============================================================================
//! \enum eTask
//! \brief TODO: document
// -----------------------------------------------------------------------------
typedef enum
{
  __START_OF_TASKS,                     //!< TODO: document; iterator
  eTASK_GUI = __START_OF_TASKS,         //!< TODO: document
  eTASK_TEST,                           //!< TODO: document
  eNUMBER_OF_TASKS                      //!< TODO: document; iterator
} eTask;


// =====[ Local Variables ]=====================================================
//static Core::tTHREAD Threads[eNUMBER_OF_TASKS];
static bool IsRunning = true;

// =====[ Local Functions ]=====================================================
static tERROR _Main_Shutdown(tERROR Error);
static void* _Main_TestTaskRun(void* Args);
static tERROR _Main_TestTaskShutdown(tERROR Error);

// =====[ Local Implementation ]================================================

// TODO: comment
static const Core::tTask TaskTable[eNUMBER_OF_TASKS]
{
//  Run                     Shutdown
  { &_Main_TestTaskRun,     NULL                          }, // eTASK_GUI
  { &_Main_TestTaskRun,     &_Main_TestTaskShutdown       }  // eTASK_TEST
};


// =============================================================================
// main
// -----------------------------------------------------------------------------
//! This is the main application execution loop.
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eLB_EXCEPT_OK: Execution occurred as requested.
//!   .
// -----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
  int Task;
  tERROR Error = ERR_NONE;

// TODO: remove
//  DB* pDb = new DB();
//  pDb->Start();

//  // Start the database.
//  Error = DB::Start();
//  if (Error != ERR_NONE) { return (_Main_Shutdown(Error)); }

  Gui::Start();

//  // Set that the application is running.
//  DB_SetEnum(eKEY_APPLICATION_IS_RUNNING, 0, eTRUE);

  // Create and start all of our tasks.
  for (Task = __START_OF_TASKS; Task < eNUMBER_OF_TASKS; Task++)
  {
    Error = Core::TaskNew(&(TaskTable[Task]));
    if (Error != ERR_NONE)
    {
      // TODO: just testing use case, cleanup when done.
      if (Error == Core::ERR_UNABLE_TO_CREATE_TASK)
        return 0;


      // Send shutdown to any tasks that may have already been created.
      Core::TaskRequestShutdown(Error);
    }
  }

  // Hold our main loop up until the shutdown request has been issued.
  // Failure to wait will cause the main loop to exit, which ultimately
  // terminates the process and all threads before the threads have completed.
  Core::TaskWaitForShutdown();

  // Shutdown the main loop.
  Error = _Main_Shutdown(0);

  // Complete gracefully.
  Core::TaskComplete(NULL);
}


// =============================================================================
// _Main_Shutdown
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR _Main_Shutdown(tERROR Error)
{
//  // Stop the UI display.
//  UI_DisplayStop(Error);
//
//  // Stop the data base.
//  DB_Stop(Error);
//
//  // Log the stop error code.
//  Core::LogError(Error);

  // Finally, return error code.
  return (Error);
}


static void* _Main_TestTaskRun(void* Args)
{
  #if dDEBUG_ENABLE
    puts("[START] _Main_TestTaskRun");
  #endif

//  while (DB_GetEnum(eKEY_APPLICATION_IS_RUNNING, 0, NULL) == eTRUE)
  while (IsRunning == true)
  {
    Core::LogMessage("_Main_TestTaskRun");
    sleep(1);
  }

  #if dDEBUG_ENABLE
    puts("[STOP] _Main_TestTaskRun");
  #endif

  // Complete gracefully.
  Core::TaskComplete(NULL);
}


static tERROR _Main_TestTaskShutdown(tERROR Error)
{
  IsRunning = false;
}
